package com.slingshot.identitylibrary.scan

import android.content.Context
import com.slingshot.identitylibrary.api.ERROR_CODE_DEVICE_NO_SUPPER
import com.slingshot.identitylibrary.api.ERROR_CODE_SCAN_TIMEOUT
import com.slingshot.identitylibrary.scan.callback.IDScanCallback
import com.slingshot.identitylibrary.scan.data.IdData
import com.speedata.libid2.IDInfor
import com.speedata.libid2.IDManager
import com.speedata.libid2.IID2Service
import io.reactivex.Observable
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.io.FileNotFoundException
import java.util.concurrent.TimeUnit

internal class IDScan(context: Context) {
    private var deviceSupper = true

    private lateinit var scanServer: IID2Service
    private var scanResult = false
    private var scanIdTask: Disposable? = null
    private var scanTaskTimeOutDisposable: Disposable? = null

    private var idScanCallback: IDScanCallback? = null

    // 扫描频率
    var settingFrequency: Long = 500

    // 超时时长
    var settingTimeout: Long = 3_0000

    init {
        init(context)
    }

    private fun init(context: Context) {
        try {
            scanServer = IDManager.getInstance()
            scanServer.initDev(context) { infor ->
                run {
                    if (!infor.isSuccess) {
                        if (scanResult) {
                            return@run
                        }
                        idScanCallback?.scanning()
                        return@run
                    }
                    scanTaskTimeOutDisposable?.dispose()
                    scanResult = true
                    idScanCallback?.scanSuccess(parseData(infor))
                    stop()
                }
            }
            deviceSupper = true
        } catch (e: FileNotFoundException) {
            deviceSupper = false
        }
    }

    fun start(idScanCallback: IDScanCallback) {
        if (!deviceSupper) {
            idScanCallback.scanStart()
            idScanCallback.scanFail(ERROR_CODE_DEVICE_NO_SUPPER)
            idScanCallback.scanFinish()
            return
        }
        this.idScanCallback = idScanCallback
        this.idScanCallback?.scanStart()
        scanResult = false
        scanIdTask?.dispose()
        scanIdTask = Observable.interval(0, settingFrequency, TimeUnit.MILLISECONDS)
            .subscribeOn(Schedulers.io())
            .subscribe({
                run {
                    scanServer.getIDInfor(false, true)
                }
            }) {}

        startTimer()
    }

    private fun startTimer() {
        scanTaskTimeOutDisposable?.dispose()
        scanTaskTimeOutDisposable =
            Observable.timer(settingTimeout, TimeUnit.MILLISECONDS).subscribeOn(Schedulers.io())
                .subscribe {
                    scanIdTask?.dispose()
                    idScanCallback?.scanFail(ERROR_CODE_SCAN_TIMEOUT)
                    idScanCallback?.scanFinish()
                }
    }

    fun stop() {
        if (!deviceSupper) {
            return
        }
        scanIdTask?.dispose()
        scanServer.getIDInfor(false, false)
        idScanCallback?.scanFinish()
    }

    fun release() {
        if (!deviceSupper) {
            return
        }
        scanServer.releaseDev()
    }

    private fun parseData(idInfor: IDInfor): IdData {
        val birthday = "${idInfor.year}-${idInfor.month}-${idInfor.day}"
        return IdData(
            removeSpace(idInfor.name),
            removeSpace(idInfor.sex),
            removeSpace(idInfor.nation),
            removeSpace(birthday),
            removeSpace(idInfor.address),
            removeSpace(idInfor.num),
            removeSpace(idInfor.qianFa),
            removeSpace(idInfor.deadLine),
            idInfor.bmps
        )
    }

    private fun removeSpace(oldString: String): String {
        return oldString.replace(" ", "")
    }
}